home *** CD-ROM | disk | FTP | other *** search
- PAGE ,132
- ;
- ; INTERRUPT DRIVEN REPLACEMENT FOR IBM BIOS INTERRUPT 14
- ;
- ; WRITTEN BY BOB MURPHY, NOVEMBER 1984.
- ;
- ; YOU MAY WANT TO CHANGE THE COMMUNICATION BUFFER SIZE FOR COM1 AND COM2
- ; DEPENDING ON THE RECIEVE SPEED, AND TYPE OF COMMUNICATIONS YOU ARE
- ; DOING. THE 2K BUFFER IS GOOD FOR MOST 1200 BAUD APPLICATIONS, BUT WILL
- ; BE EXCESSIVELY BIG FOR HUMAN-SPEED COMMUNICATIONS. THIS WILL HANDLE
- ; CONTINUOUS DATA TRANSFER AT 9600 BAUD, ASSUMING THE APPLICATION USING IT
- ; CAN ALSO KEEP UP. YOU WILL WANT TO USE A LARGER BUFFER FOR HIGHER
- ; SPEEDS IF YOU ARE DOING FILE TRANSFERS.
- ;
- ; REDUCE THE COM2 BUFFERS TO A SINGLE BYTE IF THERE IS ONLY ONE COMM
- ; CHANNEL ON YOUR PC. DO NOT REMOVE THEM ENTIRELY.
- ;
- ;
- ;
- ; INPUT PARAMETERS ARE THE SAME AS THE REGULAR BIOS ROUTINES
- ; FOR FUNCTIONS (AH) = 0 TO (AH) = 4
- ;
- ; READ CHARACTER NOWAIT - AH = 5
- ; WILL READ A CHARACTER IF ONE IS AVAILABLE, AND RETURN IMMEDIATLY. THE
- ; STATUS BYTE IN THE AH MUST BE CHECKED BY THE USER. IF AH BIT 0 = 1, THEN
- ; THE AL CONTAINS A VALID CHARACTER. IF THAT BIT IS OFF, THEN THE AL CON-
- ; TAINS GARBAGE.
- ;
- ;
- ;
- ; THE STATUS RETURNED IS A BIT DIFFERENT THAN THE IBM ROUTINE IN THAT
- ; THE BREAK DETECT BIT (AH BIT 4) IS SET IF A COMM BUFFER OVERFLOW OCCURS. THE
- ; ERROR FLAGS DO NOT NECESSARILY APPLY TO THE CHARACTER BEING READ. THEY MAY
- ; HAVE BEEN SET BY A LATER ARRIVING CHARACTER. IN SHORT, THE ERROR BITS IN THE
- ; AH ARE NOT 'REAL TIME'. ANY TIME THE STATUS IS READ (ON ANY COMMAND) THE
- ; AH ERROR BITS ARE RESET FOR THE NEXT TIME.
- ;
- ; THE TX HOLD REG EMPTY BIT INDICATES THERE IS SPACE IN THE TX OUTPUT BUFFER
- ; THE TX SHIFT REG EMPTY BIT IS USED BY THE OUTBOUND SEND ROUTINE TO DETERMINE
- ; IF IT NEEDS TO SEND A CHARACTER TO INITIATE THE TRANSMISSION PROCESS. THIS
- ; BIT IS NOT USED BY ANY SOFTWARE THAT I KNOW OF, AND YOU SHOULD NOT USE IT.
- ;
- ;
- ;
- PAGE
- INCLUDE MACROS.ASM
- BEGINCOM INT14
- JMP INIT000 ;INITIALIZE VECTORS
- BAUDTABL LABEL WORD
- DW 1047 ;110 BAUD
- DW 768 ;150 BAUD
- DW 384 ;300 BAUD
- DW 192 ;600 BAUD
- DW 96 ;1200 BAUD
- DW 48 ;2400 BAUD
- DW 24 ;4800 BAUD
- DW 12 ;9600 BAUD
- ROUTINES LABEL WORD
- DW COMMAND0 ;INITIALIZE COMMUNICATIONS CHANNEL
- DW COMMAND1 ;TRANSMIT CHARACTER IN AL ACROSS CHANNEL
- DW COMMAND2 ;WAIT FOR CHARACTER, AND RETURN IN AL
- DW COMMAND3 ;RETURN STATUS WORD (2 BYTES)
- DW COMMAND4 ;RECIEVE CHARACTER NOWAIT
- MAXCMD DW ($-ROUTINES)/2 ;MAXIMUM COMMAND VALUE (MAX AH VALUE)
- RS232_BASE EQU WORD PTR ES:0 ;ADDRESS OF RS232 BASE ADDR TBL IN SEG 40
- RS232_TIM_OUT EQU BYTE PTR ES:07CH ;RS232 TIME OUT VALUE IN LO CORE
- PAGE
- COM0000: STI ;INTERRUPTS BACK ON
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH ES
- PUSH DS ;SAVE WHAT WE CLOBBER
- MOV BX,CS
- MOV DS,BX ;MAKE THIS SEGMENT ADDRESSABLE
- MOV SI,DX ;RS232 CARD SELECT TO SI
- SHL SI,1 ;WORD OFFSET
- MOV BX,40H ;ADDRESS OF BIOS CORE AREA
- MOV ES,BX ;STASH IN DATA SEG
- MOV DX,RS232_BASE [SI] ;GET RS232 BASE ADDRESS
- OR DX,DX ;TEST FOR NO CARD PRESENT
- JZ COM0090 ;RETURN
- MOV BL,AH ;GET COMMAND INTO 2 BYTES
- SUB BH,BH ; IN THE BX REGISTER
- CMP BX,MAXCMD ;IS IT A VALID COMMAND?
- JGE COM0090 ;NO-RETURN
- SHL BX,1 ;MULTIPLY BY 2 FOR TRUE INDEX VALUE
- CALL ROUTINES [BX] ;CALL APPROPRIATE COMMAND
- ;
- ; RETURN FROM INTERRUPT 14 - NORMAL OR ABEND
- ;
- COM0090:
- POP DS
- POP ES
- POP SI
- POP DX ;RETURN FROM INT14
- POP CX
- POP BX
- IRET
- PAGE
- ;******************************************************************************
- ;
- ; INITIALIZE COMMUNICATIONS PORT
- ;
- ; DX HAS PORT ADDRESS, AH HAS PARMS. BITS 5-7 = BAUD RATE
- ; SI HAS CARD # (0-3) 3-4 = PARITY
- ; 2 = # STOP BITS
- ; 0-1 = # DATA BITS
- ;
- ;******************************************************************************
- COMMAND0 PROC NEAR
- MOV AH,AL ;SAVE INIT PARMS IN AH
- ADD DX,03 ;POINT TO LINE CONTROL REGISTER (xFB)
- MOV AL,80H ;OPEN DIVISOR LATCH
- OUT DX,AL ;SET DLAB = 1
- ;
- ; DETERMINE BAUD RATE DIVISOR, AND PUT IT IN THE BX REG
- ;
- MOV BL,AH ;BAUD RATE PARMS TO BL
- MOV CL,04 ;SHIFT VALUE
- ROL BL,CL ;MOVE TO ALIGN
- AND BX,0EH ;BX HAS INDEX INTO BAUD RATE DIVISOR TABLE
- MOV BX,BAUDTABL [BX] ;GET DIVISOR VALUE TO BX REGISTER
- ;
- ; SET BAUD RATE IN THE 8250
- ;
- SUB DX,2 ;POINT TO DIVISOR LATCH MSB (xF9)
- MOV AL,BH ;GET HI DIVISOR VALUE
- OUT DX,AL ;STICK IN DIVISOR LATCH
- DEC DX ;POINT TO DIVISOR LATCH LSB (xF8)
- MOV AL,BL ;GET LOW ORDER DIVISOR VALUE
- OUT DX,AL ;SAVE DIVISOR VALUE
- ;
- ; SET UP PARITY, STOP BITS, AND WORD LENGTH IN THE 8250
- ;
- ADD DX,3 ;POINT TO LINE CTRL REG (xFB)
- MOV AL,AH ;INPUT PARMS TO AL
- AND AL,00011111B ;BAUD BITS OFF
- OUT DX,AL ;SET UP LCR, CLOSE DIVISOR LATCH
- ;
- ; ENABLE THE 8250 INTERRUPTS
- ;
- INC DX ;POINT TO MODEM CTRL REG (xFC)
- MOV AL,00001101B ;SET UP OUT 2, DSR, AND RTS
- OUT DX,AL ;ENABLE OUT 2 ON MCR (RQD FOR INTS)
- SUB DX,3 ;POINT TO INT ENABLE REGISTER (xF9)
- MOV AL,00001111B ;ENABLE ALL INTERRUPTS
- OUT DX,AL ;PROGRAM THE IER
- ;
- ; ELIMINATE ANY PENDING INTS BEFORE IRQ CHANNEL ENABLE
- ;
- DEC DX ;POINT TO RX REGISTER (xF8)
- IN AL,DX ;KILL ANY RECIEVE INTERRUPT
- INC DX
- INC DX ;POINT TO IIR (xFA)
- IN AL,DX ;KILL ANY THRE INTS
- ADD DX,3 ;POINT TO LINE STATUS REG (xFD)
- IN AL,DX ;KILL LINE STATUS INTERRUPTS
- INC DX ;POINT TO MSR (xFE)
- IN AL,DX ;KILL MODEM STATUS INTERRUPTS
- AND AL,11110000B ;KEEP THE MODEM STATUS BITS
- MOV COM1MODM [SI],AL ;ISR STATUS REFLECTS REAL WORLD
- MOV AL,60H ;SET UP THRE,TSRE STATUS
- MOV COM1LINE [SI],60H ;SET LINE STATUS BITS
- ;
- ; RESET BUFFER POINTERS BEFORE IRQ INITIALIZATION
- ;
- MOV BX,COM1STRT [SI] ;GET START OF BUFFER (IN) POINTER
- MOV COM1SPTR [SI],BX ;START POINTER RESET
- MOV COM1EPTR [SI],BX ;END POINTER RESET
- MOV BX,OUT1STRT [SI] ;GET START OF BUFFER (OUT) POINTER
- MOV OUT1SPTR [SI],BX ;START POINTER RESET
- MOV OUT1EPTR [SI],BX ;END POINTER RESET
- ;
- ; ENABLE THE IRQ CHANNEL ON THE 8259 INTERRUPT CONTROLLER
- ;
- MOV CX,SI ;GET THE ADAPTER INVOLVED
- SHR CL,1 ;MAKE VALUE 0 OR 1
- NEG CL ;MAKE 0 OR -1 (-1 = COM2)
- ADD CL,4 ;SET SHIFT COUNT TO 3 OR 4 (COM1=4)
- MOV AH,0FEH ;SET UP MASK
- ROL AH,CL ;ALIGN FOR INTERRUPT ENABLE ON 8259
- CLI ;STOP INTS WHILE WE SCREW W/8259
- IN AL,21H ;GET CURRENT INTERRUPT MASK BYTE
- AND AL,AH ;ENABLE THE 8259 INTERRUPT
- OUT 21H,AL ;RIGHT NOW
- STI ;INTS BACK ON, COM1 OR 2 IS ACCEPTING
- ;
- ; RETURN FULL (2 BYTE) STATUS INFORMATION
- ;
- CALL COMMAND3 ;DO A FULL STATUS REQUEST
- RET ;AND WERE DONE
- COMMAND0 ENDP
- PAGE
- ;******************************************************************************
- ;
- ; SEND CHARACTER IN AL OVER COM LINE (DTR AND CTS ARE SET ON)
- ;
- ;******************************************************************************
- COMMAND1 PROC NEAR
- MOV BH,AL ;SAVE INCOMING CHARACTER
- ;
- ; TURN ON DTR AND CTS IF THEY ARE OFF
- ;
- ADD DX,4 ;POINT TO MODEM CONTROL REGISTER (xFC)
- IN AL,DX ;GET CURRENT MCR CONTENTS
- OR AL,03 ;INSURE DTR AND RTS ARE ON
- OUT DX,AL ;SEND BACK TO MCR
- ;
- ; CHECK DSR AND RTS FROM OTHER END
- ;
- MOV AH,80H ;ASSUME A TIME OUT WILL OCCUR
- CALL WAITDSR ;WAIT FOR DSR AND CTS FROM THE OTHER END
- JC COM0295 ;DSR OR CTS NOT READY - GO ERROR
- MOV BL,RS232_TIM_OUT [SI] ;GET TIME OUT VALUE FOR THIS PORT
- SUB CX,CX ;DELAY
- COM0220: TEST COM1LINE [SI],20H ;SPACE AVAIL IN BUFFER?
- JNZ COM0230 ;YES-GO SEND THE CHARACTER
- LOOP COM0220 ;ELSE-WAIT ON THE ISR TO GIVE US SOME ROOM
- DEC BL ;DEC TIME OUT COUNT
- JNZ COM0220 ;AND CONTINUE TO WAIT FOR XMIT
- JMP SHORT COM0295 ;FALL THRU = TIME OUT ERROR
- COM0230: MOV AL,BH ;RESTORE CHARACTER IN AL
- ;
- CLI ;WERE GONNA TALK, SO DONT INTERRUPT
- ;THIS WILL HOLD OFF THE LAST THRE INT
- TEST COM1LINE [SI],40H ;IS THE INTERRUPT ROUTINE RUNNING
- JNZ COM0260 ;NO-TRANSMIT THE CHARACTER IN THIS RTN
- ; ;=40=TX BUFFER COMPLETLY EMPTY
- ;
- ; THE XMIT ISR IS GOING, BUFFER THE CHARACTER
- ;
- MOV BX,OUT1EPTR [SI] ;GET END OF BUFFER POINTER
- MOV [BX],AL ;QUEUE UP THE CHARACTER FOR TRANSMISSION
- INC BX ;POINT TO NEXT AVL CHAR POS
- CMP BX,OUT1ENDB [SI] ;POINTING OFF THE END?
- JNE COM0240 ;NO-DONT REPOSITION
- MOV BX,OUT1STRT [SI] ;ELSE-RESET TO BEGINNING OF BUFFER
- COM0240: CMP BX,OUT1SPTR [SI] ;BUFFER OVERRUN OCCUR?
- JNE COM0250 ;NO-THEN WERE OK
- OR COM1LINE,20H ;POST BUFFER FULL FLAG
- COM0250: STI ;WERE DONE-SO RESTORE INTERRUPTS
- MOV OUT1EPTR [SI],BX ;SET BUFFER POSITION FOR NEXT CHARACTER
- JMP SHORT COM0290 ;RESTORE INTS AND RETURN
- ;
- ; THE XMIT ISR IS NOT GOING, SO WE WILL SEND A CHARACTER TO START IT UP
- ;
- COM0260:
- AND COM1LINE [SI],10111111B ;TURN OFF TX BUFFER EMPTY (STRT ISR)
- ;THIS IS THE SHIFT REG EMPTY BIT
- STI ;DONT NEED TO HOLD OFF INTS FOR THIS
- SUB DX,4 ;POINT TO XMIT HOLDING REGISTER (xF8)
- OUT DX,AL ;PUT CHAR IN TX HOLD REG. INTERRUPT WILL
- ;OCCUR WHEN IT HAS BEEN SENT.
- COM0290: CALL HALFSTAT ;GET STATUS OF LINE
- COM0295: RET
- COMMAND1 ENDP
- PAGE
- ;******************************************************************************
- ;
- ; RECIEVE CHARACTER FROM COMM-WAIT FOR COMM READY
- ;
- ;******************************************************************************
- COMMAND2 PROC NEAR
- MOV BL,RS232_TIM_OUT [SI] ;GET TIME OUT VALUE
- SUB CX,CX
- COM0320: TEST COM1LINE [SI],1 ;IS THERE A CHAR READY FLAG POSTED
- JNZ COM0340 ;YES-GET OUT OF KILL TIME LOOP
- LOOP COM0320 ;ELSE-WAIT ON CHARACTER
- DEC BL ;DEC TIME OUT COUNT
- JNZ COM0320 ;AND KEEP TRYING
- CALL HALFSTAT ;GET LINE STATUS
- OR AH,80H ;SET TIME OUT ERROR ALSO
- JMP SHORT COM0390 ;FAIL WITH TIME OUT
- COM0340: CALL COMMAND4 ;CALL RECIEVE CHARACTER NOWAIT
- CALL HALFSTAT ;SET LINE STATUS FLAGS
- COM0390: AND AH,10011110B ;ONLY RETURN ERROR BITS
- RET ;RETURN WITH EITHER A CHARACTER OR AN ERROR
- COMMAND2 ENDP
- PAGE
- ;******************************************************************************
- ;
- ; COMM PORT STATUS REQUEST BX GETS CLOBBERED
- ;
- ;******************************************************************************
- COMMAND3 PROC NEAR
- CLI ;KILL RS232 INTERRUPTS
- MOV AL,COM1MODM [SI] ;GET MODEM STATUS INTERRUPT DATA
- MOV BL,AL ;SAVE MODEM STATUS DATA
- AND AL,10110000B ;CLEAR THE DELTAS (AND STICKY RING INDICATOR)
- MOV COM1MODM [SI],AL ;WE READ IT, SO WE CAN TURN OFF BITS
- MOV AH,COM1LINE [SI] ;GET THE LINE STATUS FLAGS
- MOV BH,AH ;COPY THEM
- AND BH,01100001B ;KILL THE ERROR BITS (BUT DONT KILL RX AVL)
- MOV COM1LINE [SI],BH ;SAVE CHANGE OF STATE IN CORE
- STI ;INTS OK NOW THAT FLAGS HAVE BEEN GOTTEN
- MOV AL,BL ;RESTORE THE MODEM STATUS DATA
- RET ;AND RETURN TO CALLER
- COMMAND3 ENDP
- ;
- ; CALL HALFSTAT TO RETURN LINE STATUS FLAGS IN AH. BH GETS CLOBBERED
- ;
- HALFSTAT PROC NEAR ;TO GET LINE STATUS ONLY, COME HERE
- CLI
- MOV AH,COM1LINE [SI] ;GET THE LINE STATUS FLAGS
- MOV BH,AH ;COPY THEM
- AND BH,01100001B ;KILL THE ERROR BITS (BUT DONT KILL RX AVL)
- MOV COM1LINE [SI],BH ;SAVE CHANGE OF STATE IN CORE
- STI ;INTS OK NOW THAT FLAGS HAVE BEEN GOTTEN
- RET ;AND RETURN TO CALLER
- HALFSTAT ENDP
- ;
- ; WAIT FOR DSR AND RTS FROM THE OTHER END - IF TIME OUT, RETURN CARRY SET
- ;
- WAITDSR PROC NEAR
- MOV BL,RS232_TIM_OUT [SI] ;GET TIME OUT VALUE
- SUB CX,CX ;LOOP VALUE
- WAIT100: MOV AL,COM1MODM [SI] ;GET MODEM STATUS INTERRUPT DATA
- AND AL,30H ;IS DSR AND CTS ON?
- CMP AL,30H
- JE WAIT200 ;YES-RETURN NORMAL
- LOOP WAIT100 ;ELSE - TRY AGAIN
- DEC BL ;DEC TIME OUT COUNTER
- JNZ WAIT100 ;AND TRY 65536 MORE TIMES
- STC ;FALL THRU = TIME OUT
- WAIT200: RET ;RETURN TO CALLER
- WAITDSR ENDP
- PAGE
- ;*******************************************************************************
- ;
- ; RETRIEVE CHARACTER FROM INTERRUPT BUFFER
- ;
- ;
- ; RECIEVE CHARACTER NOWAIT. WILL RETURN CHARACTER IN AL IF ONE IS AVAILABLE.
- ; THE STATUS BYTE IN AH SHOULD BE TESTED FOR A X'01' TO SEE IF A CHARACTER WAS
- ; READ. IF BIT OFF, THEN AL = GARBAGE
- ;
- ;*******************************************************************************
- COMMAND4 PROC NEAR
- CLI ;DONT ALLOW RS232 INTS WHILE WE READ
- MOV AH,COM1LINE [SI] ;GET COMM STATUS FLAG
- AND COM1LINE [SI],61H ;AND ERASE ANY ERRS. LEAVE DATA AVL ALONE
- MOV BX,COM1SPTR [SI] ;GET START OF BUFFER POINTER
- CMP BX,COM1EPTR [SI] ;SAME AS END OF BUFFER POINTER?
- JE COM0560 ;IF NO CHARS - KILL DATA AVL FLAG
- ;
- ; GET A CHARACTER FROM THE BUFFER
- ;
- COM0540:
- MOV AL,[BX] ;GET A CHARACTER FROM THE COMM BUFFER
- INC BX ;
- CMP BX,COM1ENDB [SI] ;OFF THE END?
- JNE COM0550 ;NO-DONT RESET
- MOV BX,COM1STRT [SI] ;ELSE-PICK UP START OF BUFFER ADDRESS
- COM0550: MOV COM1SPTR [SI],BX ;SAVE UPDATED BUFFER POINTER
- CMP BX,COM1EPTR [SI] ;DID WE JUST REMOVE THE LAST CHARACTER
- JNE COM0580 ;NO-DONT KILL DATA AVAILABLE
- ;
- ; BUFFER CLEARED OUT - KILL THE DATA AVAILABLE FLAG
- ;
- COM0560: AND COM1LINE [SI],0FEH ;ELSE-BUFFER EMPTY, DATA AVL OFF
- AND AH,0FEH ;DO IN RETURN REG ALSO
- ;
- ; CHAR READ, IF ANY - SO ITS MILLER TIME FOR THIS ROUTINE
- ;
- COM0580: STI ;RE-ALLOW INTS
- RET ;AND HEAD OUT THE DOOR W/CHAR IN AL
- COMMAND4 ENDP
- PAGE
- ORG 0400H
- ;*COMMISR**********************************************************************
- ;
- ; RS232 INTERRUPT HANDLER
- ;
- ;******************************************************************************
- ;
- ; POINTERS AND FLAGS FOR COMM BUFFERS
- ;
- COM1SPTR DW COM1BUF ;START OF COMM BUFFER 1
- COM2SPTR DW COM2BUF ;START OF COMM BUFFER 2
- ;
- COM1EPTR DW COM1BUF ;END POINTER FOR COMM BUFFER 1
- COM2EPTR DW COM2BUF ;END POINTER FOR COMM BUFFER 2
- ;
- COM1STRT DW OFFSET COM1BUF ;ADDRESS OF COM1 BUFFER START
- COM2STRT DW OFFSET COM2BUF ;ADDRESS OF COM2 BUFFER START
- ;
- COM1ENDB DW OFFSET COM1END ;ADDRESS OF COM1 BUFFER END
- COM2ENDB DW OFFSET COM2END ;ADDRESS OF COM2 BUFFER END
- ;
- OUT1SPTR DW OUT1BUF ;START OF OUTPUT COMM BUFFER 1
- OUT2SPTR DW OUT2BUF ;START OF OUTPUT COMM BUFFER 2
- ;
- OUT1EPTR DW OUT1BUF ;END POINTER FOR OUT COMM BUFFER 1
- OUT2EPTR DW OUT2BUF ;END POINTER FOR OUT COMM BUFFER 2
- ;
- OUT1STRT DW OFFSET OUT1BUF ;ADDRESS OF OUTPUT COM1 BUFFER START
- OUT2STRT DW OFFSET OUT2BUF ;ADDRESS OF OUTPUT COM2 BUFFER START
- ;
- OUT1ENDB DW OFFSET OUT1END ;ADDRESS OF COM1 OUTPUT BUFFER END
- OUT2ENDB DW OFFSET OUT2END ;ADDRESS OF COM2 OUTPUT BUFFER END
- PAGE
- COM1LINE DB 60H ;LINE STAT FOR COMM BUFFER 1
- ; 80 = TIME OUT (USED BY RD/WRT RTN)
- ; 40 = TSRE =1= LAST CHAR HAS BEEN SENT
- ; AND THE TX BUFFER IS EMPTY
- ; 20 = THRE =1= SPACE AVAILABLE IN TX BUF
- ; 10 = BREAK DETECT/BUFFER OVERFLOW
- ; 08 = FRAMING ERROR
- ; 04 = PARITY ERROR
- ; 02 = OVERRUN ERROR
- ; 01 = DATA AVAILABLE
- COM1MODM DB 0 ;MODEM STATUS BYTE FOR COM1
- ; 80 = RLSD (CARRIER DETECT)
- ; 40 = RING INDICATOR
- ; 20 = DATA SET READY
- ; 10 = CLEAR TO SEND
- ; 08 = DELTA RLSD (CARRIER DETECT)
- ; 04 = DELTA RING INDICATOR
- ; 02 = DELTA DATA SET READY
- ; 01 = DELTA CLEAR TO SEND
- COM2LINE DB 60H ;LINE STAT FOR COMM BUFFER 2
- COM2MODM DB 0 ;MODEM STATUS BYTE FOR COM2
- ;
- COMMBASE DW 0 ;STARTING I/O ADDRESS FOR COMM CARD
- ;
- ; INPUT BUFFER FOR COMM CHANNEL 1
- ;
- COM1BUF DW 2048 DUP (?)
- COM1END EQU $
- ;
- ; INPUT BUFFER FOR COMM CHANNEL 2
- ;
- COM2BUF DW 2048 DUP (?)
- COM2END EQU $
- ;
- ; OUTPUT BUFFER FOR COMM CHANNEL 1
- ;
- OUT1BUF DW 256 DUP (?)
- OUT1END EQU $
- ;
- ; OUTPUT BUFFER FOR COMM CHANNEL 2
- ;
- OUT2BUF DW 256 DUP (?)
- OUT2END EQU $
- PAGE
- ;
- ; INTERRUPT SERVICE ROUTINES FOR COM1 AND COM2
- ;
- ISRTABLE LABEL WORD ;INTERRUPT SERVICE ROUTINE ADDR TABLE
- DW ISRMODEM ;MODEM STATUS ROUTINE (PRI 4)
- DW ISRXMIT ;XMIT DATA (PRI 3)
- DW ISRRECV ;RECIEVE DATA (PRI 2)
- DW ISRLINE ;LINE STATUS (PRI 1)
-
- ISR1000: STI ;ALLOW OTHER INTERRUPTS
- PUSH SI
- MOV SI,0 ;INDICATE COMM CARD 1
- JMP SHORT ISR0100 ;SKIP TO MAINLINE
- ISR2000: STI ;ALLOW OTHER INTERRUPTS
- PUSH SI
- MOV SI,2 ;INDICATE COMM CARD 2
- ;
- ; MAINLINE INTERRUPT RTN
- ;
- ISR0100: PUSH AX ;SAVE ALL REGS USED
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DS
- ;
- ; SET UP BASE REGISTERS
- ;
- MOV AX,40H ;ADDRESS OF RS232 CARD I/O PORT ADDRESSES
- MOV DS,AX ;DS = CS FOR DATA BUFFERS
- MOV DX,WORD PTR [SI] ;GET COMM CARD BASE ADDRESS
- MOV AX,CS
- MOV DS,AX ;DS POINTS TO PGM FOR USE OF COMM BUFFERS
- MOV COMMBASE,DX ;SAVE COMM CARD BASE FOR SECOND TIME THROUGH
- ISR0120: MOV DX,COMMBASE ;GET STARTING I/O ADDRESS FOR COMM CARD
- INC DX
- INC DX ;GET PORT FOR INT IDENTIFICATION REG
- IN AL,DX ;GET IIR CONTENTS
- TEST AL,1 ;IS AN INTERRUPT PENDING?
- JNZ ISR0140 ;NO-EOI TO 8259 & LEST GET OUT OF HERE
- CBW ;ELSE-GET INDEX INTO TABLE
- MOV BX,AX ;COPY TO USEFUL REGISTER
- CALL ISRTABLE [BX] ;CALL APPROPRIATE ROUTINE
- JMP ISR0120 ;AND KEEP CHECKING UNTIL ALL INTS DONE
- ISR0140:
- ;
- ; SIGNAL END OF INTERRUPT TO 8259
- ;
- CLI ;KILL INTERRUPTS
- MOV AL,20H ;NON-SPECIFIC EOI
- OUT 20H,AL ;SEND IT
- STI ;RE-ALLOW INTERRUPTS
- ;
- ; END OF INTERRUPT CODE
- ;
- POP DS
- POP DX
- POP CX
- POP BX
- POP AX
- POP SI
- IRET
- PAGE
- ;**ISRLINE*********************************************************************
- ;
- ; LINE STATUS ERROR HANDLER
- ;
- ;******************************************************************************
- ISRLINE PROC NEAR
- ADD DX,3 ;LINE STATUS REGISTER (xFD)
- IN AL,DX ;GET STATUS
- AND AL,00011110B ;MASK NON-ERROR BITS
- OR COM1LINE [SI],AL ;AND SAVE IN COMM FLAGS
- RET
- ISRLINE ENDP
-
-
-
- ;**ISRRECV*********************************************************************
- ;
- ; INBOUND CHARACTER INTERRUPT SERVICE ROUTINE
- ;
- ;******************************************************************************
- ISRRECV PROC NEAR
- ;
- ; GET INCOMING CHARACTER AND BUFFER IT
- ;
- DEC DX
- DEC DX ;RECEIVE BUFFER REGISTER (xF8)
- SUB AH,AH ;SET FLAGS = 0
- IN AL,DX ;GET INPUT CHARACTER
- MOV BX,COM1EPTR [SI] ;COM-BUF END POINTER
- MOV DX,BX ;SAVE POINTER BEFORE INCREMENT
- INC BX ;BUMP POINTER
- CMP BX,COM1ENDB [SI] ;PAST END?
- JNE ISR0220 ;JUMP IF NOT
- MOV BX,COM1STRT [SI] ;ELSE POINT TO START
- ISR0220: CMP BX,COM1SPTR [SI] ;OVERFLOW IF HEAD = TAIL
- JE ISR0240 ;OVERFLOW
- MOV COM1EPTR [SI],BX ;AND NEW INPUT POINTER
- MOV BX,DX ;GET UNBUMPED POINTER BACK
- MOV [BX],AL ;NO OVERFLOW, SAVE CHAR IN COM1BUF
- OR AH,1
- JMP ISR0280 ;WERE ALL DONE RECIEVING CHARACTER
- ISR0240: OR AH,10H ;SET OVERFLOW/BREAK FLAG
- ISR0280: OR COM1LINE [SI],AH ;PUT IN LINE STATUS FIELD
- RET
- ISRRECV ENDP
- PAGE
- ;**ISRXMIT*********************************************************************
- ;
- ; OUTBOUND CHARACTER INTERRUPT SERVICE ROUTINE
- ;
- ; POST XMIT SHIFT REG EMPTY WHEN LAST CHAR PLACED IN XMIT HOLD REG.
- ; KILL XMIT HOLD REG EMPTY WHEN XMIT BUFFER IS FILLED UP
- ;
- ;******************************************************************************
- ISRXMIT PROC NEAR
- ;
- MOV AH,40H ;ASSUME WE WILL SEND LAST CHARACTER
- MOV BX,OUT1SPTR [SI] ;GET START OF BUFFER POINTER
- CMP BX,OUT1EPTR [SI] ;IS THE BUFFER EMPTY?
- JE ISR0480 ;YES-SKIP THE DATA TRANSMISSION
- DEC DX
- DEC DX ;POINT TO XMIT HOLDING REGISTER (xF8)
- MOV AL,[BX] ;GET CHARACTER FROM BUFFER
- OUT DX,AL ;SEND IT ON ITS WAY
- INC BX ;BUMP THE OUTPUT BUFFER POINTER
- CMP BX,OUT1ENDB [SI] ;POINTING AT THE END OF THE BUFFER
- JNE ISR0420 ;NO-POINTER IS OK
- MOV BX,OUT1STRT [SI] ;ELSE - POINT TO BUFFER START
- ISR0420: MOV OUT1SPTR [SI],BX ;SAVE NEW BUFFER POINTER
- OR AH,20H ;SEND BACK A TX HOLD REG EMPTY INDICATION
- CMP OUT1EPTR [SI],BX ;DID WE JUST EMPTY THE BUFFER? *T
- JE ISR0480 ;YES-THEN THERE WONT BE ANY MORE INTS *T
- AND AH,10111111B ;AND SET BIT SAYS WERE OPERATING
- ISR0480: OR COM1LINE [SI],AH ;STUFF IT IN THE FLAGS
- RET
- ISRXMIT ENDP
- ;**ISRMODEM********************************************************************
- ;
- ; MODEM STATUS INTERRUPT SERVICE ROUTINE
- ;
- ;******************************************************************************
- ISRMODEM PROC NEAR
- ADD DX,4 ;POINT TO MODEM STATUS REGISTER (xFE)
- IN AL,DX ;GET CONTENTS & CLEAR INTERRUPT
- MOV AH,AL
- AND AH,11110000B ;GET ACTUAL SIGNAL LINE STATUS
- OR AL,COM1MODM [SI] ;OR IN PREVIOUS LINE STATUS
- AND AL,01001111B ;GET DELTA VALUES ALONE
- ;AND LEAVE RING INDICATOR ON
- OR AL,AH ;SEVERAL DELTA VALUES, BUT ONLY CURRENT
- MOV COM1MODM [SI],AL ; MODEM STATUS INTO MODEM STATUS FIELD
- RET ;AND WERE DONE
- ISRMODEM ENDP
- PRGMEND EQU $ ;END OF CODE TO SAVE IN CORE
- PAGE
- ;**NONRES**********************************************************************
- ;
- ; THE FOLLOWING IS NON-RESIDENT CODE
- ;
- ;******************************************************************************
- ;
- ; PROGRAM INITIALIZATION
- ;
- INIT000: MOV DX,OFFSET COM0000 ;POINT TO START OF ROUTINE
- @DOS 25H,14H ;RESET VECTOR 14
- MOV DX,OFFSET ISR1000 ;ADDRESS OF COM 1 HANDLER
- CLI ;STOP INTS DURING 8259 VECTOR UPDATE
- @DOS 25H,0CH ;RESET VECTOR 0C (IRQ4-FOR COM1)
- MOV DX,OFFSET ISR2000 ;ADDRESS OF COM 2 HANDLER
- @DOS 25H,0BH ;RESET VECTOR 0B (IRQ3-FOR COM2)
- STI
- MOV DX,OFFSET PRGMEND ;POINT TO END OF CODE TO KEEP FOREVER
- INT 27H ;TERMINATE & STAY RESIDENT
- ENDCOM INT14